from skimage import io, transform
import glob
import os
import numpy as np
import matplotlib.pyplot as plt
import numpy as np
from scipy.interpolate import spline


class Judge:
    # 证明模型优劣的一个类

    '''
    current_degree: 当前作为正样本的等级
    original_label: 原始数据对应的标签值
    result_label: 模型得出的数据对应的标签值
    '''

    def __init__(self, original_label, result_label):
        self.original_label = original_label
        self.result_label = result_label

    # 返回TP、TN、FP、FN
    # FN：False Negative,被判定为负样本，但事实上是正样本。
    # FP：False Positive,被判定为正样本，但事实上是负样本。
    # TN：True Negative,被判定为负样本，事实上也是负样本。
    # TP：True Positive,被判定为正样本，事实上也是正样本。

    # (TP+TN)/(TP+FN+FP+TN)
    # 即分对的数目除以总数
    # 准确率！
    def accuracy_for_HER2(self):
        assert len(self.original_label) == len(self.result_label)
        data_number = len(self.original_label)
        correct_sample = 0  # 分对的数目
        for i in range(data_number):
            if self.original_label[i] == self.result_label[i]:
                correct_sample += 1
        accuracy = correct_sample/data_number
        return accuracy


    # TP/(TP + FP)
    # 即判断正确的正样本数目/被判定为正样本的数目
    # 对于HER2，由于有4种等级，所以这里在算某一种等级时，将它作为正样本，其他作为负样本
    # 精准度
    def precision_for_HER2(self,current_degree):
        assert len(self.original_label) == len(self.result_label)
        data_number = len(self.original_label)
        result_positive_number = 0 # TP+FP
        real_positive_number = 0 # TP

        for i in range(data_number):
            if self.result_label[i] == current_degree:
                result_positive_number += 1

        for i in range(data_number):
            if self.original_label[i] == self.result_label[i] and \
                (self.result_label[i] == current_degree):
                real_positive_number += 1

        precision = real_positive_number/result_positive_number
        return precision


    # TP/(TP + FN)
    # 即判断正确的正样本数目/原来数据中为正样本的所有数目
    # 对于HER2，由于有4种等级，所以这里在算某一种等级时，将它作为正样本，其他作为负样本
    # 召回率，也叫TPR （命中率）
    def recall_for_HER2(self, current_degree):
        assert len(self.original_label) == len(self.result_label)
        data_number = len(self.original_label)
        original_positive_number = 0 # TP+FN
        real_positive_number = 0 # TP

        for i in range(data_number):
            if self.original_label[i] == current_degree:
                original_positive_number += 1

        for i in range(data_number):
            if self.original_label[i] == self.result_label[i] and \
                (self.result_label[i] == current_degree):
                real_positive_number += 1

        recall = real_positive_number/original_positive_number
        return recall

    # FP/(FP + TN)
    # 即判断为正样本的负样本数目/原来数据中为负样本的所有数目

    def FPR_for_HER2(self, current_degree):
        assert len(self.original_label) == len(self.result_label)
        data_number = len(self.original_label)
        original_negative_number = 0 # FP+TN
        false_positive_number = 0 # FP

        for i in range(data_number):
            if self.original_label[i] != current_degree:
                original_negative_number += 1

        for i in range(data_number):
            if (self.original_label[i] != current_degree) and \
                (self.result_label[i] == current_degree):
                false_positive_number += 1

        FPR = false_positive_number/original_negative_number
        return FPR


class Display:

    # FPR为X轴，TPR(recall)为Y轴
    def draw_ROC_curve(self,FPR, TPR, linspace_number = 200):
        FPR_array = np.array(FPR)
        TPR_array = np.array(TPR)
        xnew = np.linspace(FPR_array.min(), FPR_array.max(), linspace_number)  # 300 represents number of points to make between T.min and T.max

        power_smooth = spline(FPR_array, TPR_array, xnew)

        plt.plot(xnew, power_smooth)
        plt.title(u'ROC曲线',fontproperties='SimHei')
        plt.xlabel("FPR")
        plt.ylabel("TPR")
        plt.show()


    # R(recall)为X轴，P(precision)为Y轴
    def draw_PR_curve(self,R, P, linspace_number = 200):
        np_R = np.array(R)
        np_P = np.array(P)
        xnew = np.linspace(np_R.min(), np_R.max(), linspace_number)  # 300 represents number of points to make between T.min and T.max

        power_smooth = spline(np_R, np_P, xnew)

        plt.plot(xnew, power_smooth)
        plt.title(u'PR曲线',fontproperties='SimHei')
        plt.xlabel("R(recall)")
        plt.ylabel("P(precision)")
        plt.show()


    def draw_data_processing_curve(self,X, Y1, Y2, title_name, linspace_number = 200):
        np_X1 = np.array(X)
        np_Y1 = np.array(Y1)

        np_X2 = np.array(X)
        np_Y2 = np.array(Y2)

        plt.plot(np_X1, np_Y1, color='blue', linestyle = '-.',label='LPA')
        plt.plot(np_X2, np_Y2, color='red', linestyle = ':',label='SVM')
        plt.legend()
        # plt.title(title_name)
        plt.xlabel("the number of training image")
        plt.ylabel("accuracy")
        plt.show()